package com.tao.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.tao.constant.MessageConstant;
import com.tao.context.UserContext;
import com.tao.mapper.*;
import com.tao.pojo.dto.*;
import com.tao.pojo.entity.AddressBook;
import com.tao.pojo.entity.Order;
import com.tao.pojo.entity.OrderDetail;
import com.tao.pojo.entity.ShoppingCart;
import com.tao.pojo.vo.OrderPayVo;
import com.tao.pojo.vo.OrderSubmitVo;
import com.tao.pojo.vo.OrderVo;
import com.tao.result.PageResult;
import com.tao.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Slf4j
@Service
public class OrderService1 implements OrderService {

    @Autowired
    OrderMapper orderMapper;
    @Autowired
    ShoppingCartMapper shoppingCartMapper;
    @Autowired
    OrderDetailMapper orderDetailMapper;
    @Autowired
    AddressBookMapper addressBookMapper;
    @Autowired
    UserMapper userMapper;

    @Override
    @Transactional
    public OrderSubmitVo orderSubmit(OrderSubmitDTO orderSubmitDto) {
        log.info("接收到的DTO为:{}",orderSubmitDto);
        AddressBook addressBook = addressBookMapper.getById(orderSubmitDto.getAddressBookId());
        log.info("该用户地址薄信息:{}",addressBook);
        //判断业务异常 地址空 购物车空
        if(addressBook == null)
            throw new RuntimeException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        if(shoppingCartMapper.getAllByUserId(UserContext.getThreadUserId()) == null || shoppingCartMapper.getAllByUserId(UserContext.getThreadUserId()).isEmpty())
            throw new RuntimeException(MessageConstant.SHOPPING_CART_IS_NULL);

        Order order = new Order();
        BeanUtils.copyProperties(orderSubmitDto,order);
        order.setStatus(Order.PENDING_PAYMENT);
        order.setUserId(UserContext.getThreadUserId());
        order.setOrderDate( LocalDateTime.now());
        order.setPayStatus(Order.UN_PAID);
        order.setNumber(String.valueOf(System.currentTimeMillis())+UUID.randomUUID());
        order.setPhone(addressBook.getPhone());
        order.setAddress(addressBook.getDetail());
        order.setConsignee(addressBook.getConsignee());
        log.info("完整order数据为:{}",order);
        orderMapper.orderSubmit(order);

        //添加关联表数据 也可以用动态sql批量插入（效率高，访问一次持久层！！！！）
        OrderDetail orderDetail = new OrderDetail();
        shoppingCartMapper.getAllByUserId(UserContext.getThreadUserId()).forEach(shoppingCart -> {
            orderDetail.setOrderId(order.getId());
            orderDetail.setAmount(shoppingCart.getPrice());
            orderDetail.setProductFlavor(shoppingCart.getProductFlavor());
            orderDetail.setImage(shoppingCart.getImage());
            orderDetail.setNumber(shoppingCart.getNumber());
            orderDetail.setProductId(shoppingCart.getProductId());
            orderDetail.setSetmealId(shoppingCart.getSetmealId());
            orderDetail.setName(shoppingCart.getName());
            log.info("完整订单明细数据为:{}",orderDetail);
            orderDetailMapper.insertOrderDetail(orderDetail);
            log.info("插入成功");
        });


        //下单后清空购物车
        shoppingCartMapper.cleanShoppingCart(CleanShoppingCartDto.builder().userId(UserContext.getThreadUserId()).build());
        log.info("已清空购物车");

        OrderSubmitVo orderSubmitVo = new OrderSubmitVo(order.getId(),order.getNumber(),order.getTotalPrice(),order.getOrderDate());
        log.info("VO数据为:{}",orderSubmitVo);
        return orderSubmitVo;
    }

    public void orderPay(OrderPayDto orderPayDto){
        //修改状态，返回
        Order order = Order.builder()
                .id(orderPayDto.getId())
                .checkoutTime(LocalDateTime.now())
                .payMethod(orderPayDto.getPayMethod())
                .payStatus(Order.PAID)
                .status(Order.TO_BE_CONFIRMED)
                .build();
        orderMapper.updateOrder(order);
    }

    @Override
    public void orderCancel(OrderCancelDto orderCancelDto) {
        log.info("接收到的信息为:{}",orderCancelDto);

        Order order= orderMapper.getOrderById(orderCancelDto.getId());
        Order order1 = new Order();
        //判异常
        if(order==null ){
            throw new RuntimeException("不存在该订单，无法取消");
        }
        if (order.getStatus()>2){
            throw new RuntimeException("订单已接单，请联系商家");
        }


        /*
        * 待接单可直接调用支付退款功能
        * */
        if (order.getStatus().equals(Order.TO_BE_CONFIRMED)){
            //调用微信支付退款接口
//            weChatPayUtil.refund(
//                    ordersDB.getNumber(), //商户订单号
//                    ordersDB.getNumber(), //商户退款单号
//                    new BigDecimal(0.01),//退款金额，单位 元
//                    new BigDecimal(0.01));//原订单金额
            log.info("退款成功");
            order1.setPayStatus(Order.REFUND);
        }

        order.setStatus(Order.CANCELLED);
        order.setCancelTime(LocalDateTime.now());
        orderMapper.updateOrder(order1);
        log.info("订单取消成功");
    }

    @Override
    public PageResult getHistoryOrder(PageSelectHistoryDto pageSelectHistoryDto) {
        log.info("接收到的DTO为:{}",pageSelectHistoryDto);
        pageSelectHistoryDto.setUserId(UserContext.getThreadUserId());
        PageHelper.startPage(pageSelectHistoryDto.getPage(),pageSelectHistoryDto.getPageSize());
        Page<OrderVo> page=orderMapper.getHistoryOrder(pageSelectHistoryDto);
        //page 相当于集合，可进行遍历，封装每个VO的detail,userName（当select结果为集合时，每个元素还需要封装其他表信息时，只能通过遍历专门封装别的表的信息）
        page.forEach(orderVo -> {
            orderVo.setUserName(userMapper.getUserByIdMapper(UserContext.getThreadUserId()).getName());
            List<OrderDetail> orderDetailList=orderDetailMapper.getOrderDetail(orderVo.getId());
            orderVo.setOrderDetailList(orderDetailList);
        });
        PageResult pageResult =new PageResult(page.getTotal(),page.getResult());
        return pageResult;
    }

    @Override
    public OrderVo getOrderDetail(Integer id) {
        //像这种vo里有list的只能调用多个mapper，无法多表查询，因为无法根据名字封装
        Integer userId = UserContext.getThreadUserId();
        log.info("查询用户:{}的:{}订单详细信息",userId,id);
        Order order = orderMapper.getOrderById(id);
        OrderVo orderVo = new OrderVo();
        BeanUtils.copyProperties(order,orderVo);
        orderVo.setUserName(userMapper.getUserByIdMapper(userId).getName());
        orderVo.setOrderDetailList(orderDetailMapper.getOrderDetail(id));
        log.info("完整订单信息为:{}",orderVo);
        return orderVo;

    }

    @Override
    public void repetitionOrder(Integer id) {
        log.info("对订单:{}再来一单",id);
        //错误：OrderVo orderVo = orderMapper.getOrderById(id); 只需要获取orderDetail的信息即可
        List<OrderDetail> orderDetailList = orderDetailMapper.getOrderDetail(id);
        log.info("对应订单信息为:{}",orderDetailList);
        //由于需要插入很多shoppingcart对象，每个对象依据的都是orderdetaillist中的每个对象
        //为了提高阅读性，这种一个集合需要根据另一个集合生成的操作
        //直接用stream流的map方法
        List<ShoppingCart> shoppingCartList=orderDetailList.stream()
                .map(orderDetail -> {
                    ShoppingCart shoppingCart = new ShoppingCart();
                    BeanUtils.copyProperties(orderDetail,shoppingCart,"id");
                    shoppingCart.setUserId(UserContext.getThreadUserId());
                    shoppingCart.setCreateTime(LocalDateTime.now());
                    return shoppingCart;
                })
                .collect(Collectors.toList());
        log.info("需要批量插入的购物车数据为:{}",shoppingCartList);
        //可遍历插入，也可以一次性批量插入，推荐后者，访问一次数据库，效率高
        shoppingCartMapper.addShoppingCartList(shoppingCartList);
        log.info("一次性批量插入成功");
    }
}
